﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using ScrumFactory.Composition.ViewModel;
using ScrumFactory.Composition;
using System.ComponentModel;
using System.ComponentModel.Composition;
using ScrumFactory.Services;
using System.Collections.ObjectModel;

namespace ScrumFactory.ProjectTeam.ViewModel {

    /// <summary>
    /// Project Team View Model.
    /// </summary>
    [Export(typeof(IPanelViewModel))]
    [Export(typeof(IProjectTeamViewModel))]
    public class ProjectTeamViewModel : BasePanelViewModel, IPanelViewModel, IProjectTeamViewModel, INotifyPropertyChanged {


        private IEventAggregator aggregator;
        private ITeamService teamServices;
        private IProjectsService projectsServices;
        private IBackgroundExecutor executor;

        private System.Windows.Data.CollectionViewSource membershipViewSource;

        private Role roleToAdd;

        private ICollection<IProjectMembershipViewModel> projectMemberships;

        [ImportingConstructor]
        public ProjectTeamViewModel(
            [Import]IEventAggregator eventAggregator,
            [Import]IProjectsService projectsServices,
            [Import]ITeamService teamServices,
            [Import]IBackgroundExecutor backgroundExecutor
            ) {

            this.aggregator = eventAggregator;
            this.projectsServices = projectsServices;
            this.teamServices = teamServices;
            this.executor = backgroundExecutor;

            ShowRolesListCommand = new DelegateCommand(ShowRolesList);
            AddNewMemberCommand = new DelegateCommand<Role>(ShowMemberLookup);
            RemoveMemberCommand = new DelegateCommand<IProjectMembershipViewModel>(RemoveMember);

            membershipViewSource = new System.Windows.Data.CollectionViewSource();
            membershipViewSource.GroupDescriptions.Add(new System.Windows.Data.PropertyGroupDescription("Role.RoleName"));
            
            
            aggregator.Subscribe<Project>(ScrumFactoryEvent.ViewProjectDetails, OnViewProjectDetails);
            aggregator.Subscribe<ICollection<Role>>(ScrumFactoryEvent.ProjectRolesLoaded, roles => { OnPropertyChanged("Roles"); });
            aggregator.Subscribe<Role>(ScrumFactoryEvent.ProjectRoleChanged, role => { membershipViewSource.View.Refresh(); });
  
        }

        private void RemoveMember(IProjectMembershipViewModel membershipVM) {
            executor.StartBackgroundTask(
                () => {
                    teamServices.RemoveProjectMembership(membershipVM.ProjectMembership.MemberUId, membershipVM.ProjectMembership);
                },
                () => {
                    ProjectMemberships.Remove(membershipVM);
                    Project.Memberships.Remove(membershipVM.ProjectMembership);
                });            
        }
          
        private void OnViewProjectDetails(Project project) {
            Project = project;
            LoadProjectMembers();
        }


        private void LoadProjectMembers() {
            if (Project == null)
                return;
            IsLoadingData = true;


            executor.StartBackgroundTask<ICollection<MemberProfile>>(
                () => teamServices.GetProjectMembers(Project.ProjectUId), OnProjectMembersLoaded);
        }

        private void OnProjectMembersLoaded(ICollection<MemberProfile> members) {
          
            ObservableCollection<IProjectMembershipViewModel> memberships = new ObservableCollection<IProjectMembershipViewModel>();
            Project.Memberships = new List<ProjectMembership>();
            if (members != null) {
                foreach (MemberProfile m in members) {
                    if (m.Memberships != null) {
                        foreach (ProjectMembership ms in m.Memberships) {
                            Role role = Project.Roles.SingleOrDefault(r => r.RoleUId == ms.RoleUId);
                            if (role != null) {
                                memberships.Add(new ProjectMembershipViewModel(executor, teamServices, ms, m, role));
                                Project.Memberships.Add(ms);
                            }
                        }
                    }
                }
            }

            ProjectMemberships = memberships;

            membershipViewSource.Source = ProjectMemberships;            

            OnPropertyChanged("GroupedProjectMemberships");

            IsLoadingData = false;

        }

        public ICollectionView GroupedProjectMemberships {
            get {
                return membershipViewSource.View;
            }
        }


        [Import(typeof(IProjectTeamView))]
        public IProjectTeamView View { get; set; }

        /// <summary>
        /// Gets or sets the roles list view.
        /// </summary>
        /// <value>The roles list view.</value>
        [Import(typeof(IRolesListView))]
        public IRolesListView RolesListView { get; set; }    

        /// <summary>
        /// Shows the roles list.
        /// </summary>
        private void ShowRolesList() {
            aggregator.Publish<IPanelViewModel>(ScrumFactoryEvent.OpenNewWindow, (IPanelViewModel) RolesListView.Model);
        }

        public void ShowMemberLookup(Role role) {
            roleToAdd = role;
            MemberLookupViewModel vm = new MemberLookupViewModel(aggregator, teamServices, executor, roleToAdd, OnMemberSelectedToAdd);
            vm.Show();
            roleToAdd = null;
        }

        public void OnMemberSelectedToAdd(IMemberViewModel memberVM) {
            MemberProfile member = memberVM.MemberProfile;
            ProjectMembership ms = new ProjectMembership() { MemberUId = member.MemberUId, ProjectUId = Project.ProjectUId, RoleUId = roleToAdd.RoleUId };
            ProjectMemberships.Add(new ProjectMembershipViewModel(executor, teamServices, ms, member, roleToAdd));
            Project.Memberships.Add(ms);
            executor.StartBackgroundTask(
                () => { teamServices.AddProjectMembership(member.MemberUId, ms); },
                ()=>{});            
        }

        #region IPanelViewModel Members

        /// <summary>
        /// Gets the name of the panel.
        /// </summary>
        /// <value>The name of the panel.</value>
        public string PanelName {
            get {
                return Properties.Resources.Team;
            }
        }

        /// <summary>
        /// Gets the view.
        /// </summary>
        /// <value>The view.</value>
        object IPanelViewModel.View {
            get { return this.View; }
        }

        /// <summary>
        /// Gets the panel display order when it is displayed at the view.
        /// </summary>
        /// <value>The panel display order.</value>
        public int PanelDisplayOrder {
            get {
                return 200;
            }
        }

        /// <summary>
        /// Gets the panel Unique id.
        /// </summary>
        /// <value>The panel Unique id.</value>
        public string PanelUId {
            get {
                return "PROJECT_TEAM_TAB";
            }
        }

        /// <summary>
        /// Gets the panel placement.
        /// </summary>
        /// <value>The panel placement.</value>
        public PanelPlacements PanelPlacement {
            get {
                return PanelPlacements.ProjectTab;
            }
        }

        #endregion

        #region IProjectTeamViewModel Members

        /// <summary>
        /// Gets the project.
        /// </summary>
        /// <value>The project.</value>
        public Project Project { get; private set; }


        /// <summary>
        /// Gets the project roles.
        /// </summary>
        /// <value>The roles.</value>
        public ICollection<IRoleViewModel> Roles {
            get {
                return RolesListView.Model.Roles;
            }
        }

        /// <summary>
        /// Gets the project members.
        /// </summary>
        /// <value>The project members.</value>
        public ICollection<IProjectMembershipViewModel> ProjectMemberships {
            get {
                return projectMemberships;
            }
            set {
                projectMemberships = value;
                OnPropertyChanged("ProjectMemberships");
            }
        }

        /// <summary>
        /// Gets the show roles list command.
        /// </summary>
        /// <value>The show roles list command.</value>
        public ICommand ShowRolesListCommand { get; private set; }


        /// <summary>
        /// Gets the add new member command.
        /// </summary>
        /// <value>The add new member command.</value>
        public ICommand AddNewMemberCommand { get; private set; }

        /// <summary>
        /// Gets the remove member command.
        /// </summary>
        /// <value>The remove member command.</value>
        public ICommand RemoveMemberCommand { get; private set; }


        #endregion

    }
}
